//-----------------------------------------------------------------------------
//  File          : coremain.c
//  Module        :
//  Description   : Main Entry.
//  Author        : Auto Generate by coremain_c.bat
//  Notes         :
//
// ============================================================================
// | Naming conventions                                                       |
// | ~~~~~~~~~~~~~~~~~~                                                       |
// |         Struct/Array : Leading s                                         |
// |             Constant : Leading K                                         |
// |      Global Variable : Leading g  (variable use outside one C file)      |
// |                                                                          |
// |   BYTE( 8 Bits) size : Leading b                                         |
// |   CHAR( 8 Bits) size : Leading c                                         |
// |   WORD(16 Bits) size : Leading w                                         |
// |  DWORD(32 Bits) size : Leading d                                         |
// |    int(32 Bits) size : Leading i                                         |
// | DDWORD(64 Bits) size : Leading dd                                        |
// |              Pointer : Leading p                                         |
// |                                                                          |
// |    Function argument : Leading a                                         |
// |       Local Variable : All lower case                                    |
// |                                                                          |
// | Examples:                                                                |
// |                Array : Leading s, (sb = arrary of byte, etc)             |
// |              Pointer : Leading p, (pb = pointer of byte, etc)            |
// ============================================================================
//
//  Date          Who         Action
//  ------------  ----------- -------------------------------------------------
//  DD MMM  YYYY  coremain_c  Initial Version.
//-----------------------------------------------------------------------------
#include <stdio.h>
#include "system.h"
#include "midware.h"
#include "sysutil.h"
#if (T800)
#include "spectrasym.h"
#endif
#include "spectralogo.h"
#include "hardware.h"
#include "message.h"
#include "kbdutil.h"
#include "apmfunc.h"
#include "rmenu.h"
#include "comm.h"
#include "stis.h"
#include "termdata.h"
#include "batchsys.h"
#include "emvtrans.h"
#include "ecrdll.h"
#include "pp300dll.h"
#include "apmconfig.h"
#include "apmtest.h"
#include "coremain.h"
#include "key2dll.h"

//-----------------------------------------------------------------------------
//      Prototypes
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//      Defines
//-----------------------------------------------------------------------------
#define MAX_APP_LIST    16

//-----------------------------------------------------------------------------
//      Globals
//-----------------------------------------------------------------------------
static struct RMENUDAT gApmMenu[MAX_APP_LIST+MAX_APM_FUNC+1];

//-----------------------------------------------------------------------------
//      Export Func
//-----------------------------------------------------------------------------
void XF_GetHwHdl(DWORD x)                 { os_appcall_return(GetHwHandle(x)); }
// Kbd Func
void XF_ClrKeyin()                        { ClearKeyin(); os_appcall_return(0); }
void XF_GetKeyin()                        { os_appcall_return(GetKeyin()); }
void XF_WaitKey(DWORD x, DWORD y)         { os_appcall_return(WaitKeyCheck(x, y)); }
void XF_YesNo()                           { os_appcall_return(YesNo()); }
void XF_GetKbd(DWORD x, DWORD y, BYTE *z) { os_appcall_return(GetKbd(x, y, z)); }
void XF_SetKbdTO(DWORD x)                 { SetKbdTimeout(x); os_appcall_return(0); };
void XF_GetKbdTO()                        { os_appcall_return(GetKbdTimeout()); }

// Comm Func
void XF_PackComm(struct COMMPARAM *x)     { PackComm(x); os_appcall_return(0); };
void XF_PreConnect()                      { PreConnect(); os_appcall_return(0); };
void XF_ConnectOK(DWORD x)                { os_appcall_return(ConnectOK(x)); };
void XF_SendRcvd(struct COMMBUF *x, struct COMMBUF *y) {os_appcall_return(SendRcvd(x, y)); };
void XF_SendRcvd_my(struct COMMBUF *x, struct COMMBUF *y) {os_appcall_return(SendRcvd_my(x, y)); };
void XF_Receive_gprs(struct COMMBUF *x)   { os_appcall_return(Receive_gprs(x)); };
void XF_FlushComm()                       { FlushComm(); os_appcall_return(0); };
void XF_ResetComm()                       { os_appcall_return(ResetComm()); };

// STIS Func
void XF_GetTermData(struct TERM_DATA *x)              { os_appcall_return(GetTermData(x)); }
void XF_GetTermCfg(struct TERM_CFG *x)                { os_appcall_return(GetTermCfg(x)); }
void XF_GetCardCount(void)                            { os_appcall_return(GetCardCount()); }
void XF_GetCardTbl(DWORD x, struct CARD_TBL *y)       { os_appcall_return(GetCardTbl(x, y)); }
void XF_GetIssuerCount(void)                          { os_appcall_return(GetIssuerCount()); }
void XF_GetIssuerTbl(DWORD x, struct ISSUER_TBL *y)   { os_appcall_return(GetIssuerTbl(x, y)); }
void XF_GetAcqCount(void)                             { os_appcall_return(GetAcqCount()); }
void XF_GetAcqTbl(DWORD x, struct ACQUIRER_TBL *y)    { os_appcall_return(GetAcqTbl(x, y)); }
void XF_GetDescCount(void)                            { os_appcall_return(GetDescCount()); }
void XF_GetDescTbl(DWORD x, struct DESC_TBL *y)       { os_appcall_return(GetDescTbl(x, y)); }
void XF_GetLogoCount(void)                            { os_appcall_return(GetLogoCount()); }
void XF_GetLogoTbl(DWORD x, struct LOGO_TBL *y)       { os_appcall_return(GetLogoTbl(x, y)); }
void XF_GetExParamCount(void)                         { os_appcall_return(GetExParamCount()); }
void XF_GetExtraParam(DWORD x, struct EXTRA_PARAM *y) { os_appcall_return(GetExtraParam(x, y)); }
void XF_GetPending(int x)                             { os_appcall_return(GetPending(x)); }
void XF_SetPending(int x, BYTE y)                     { SetPending(x,y); os_appcall_return(0); }
void XF_GetBatchNo(DWORD x, BYTE *y)                  { os_appcall_return(GetBatchNo(x, y)); }
void XF_SetBatchNo(DWORD x, BYTE *y)                  { SetBatchNo(x, y); os_appcall_return(0); }
void XF_SelectAcquirer(int x)                         { os_appcall_return(SelectAcquirer(x)); }
void XF_SetROC(void *x)                               { SetROC(x); os_appcall_return(0); }
void XF_SetTrace(void *x)                             { SetTrace(x); os_appcall_return(0); }
void XF_StisClr(void)                                 { CleanStisTable(); os_appcall_return(0); };
void XF_StisAddTbl(int x, void *y)                    { os_appcall_return(StisAdd(x, y)); };
void XF_TermDataClr(void)                             { CleanTermData(); os_appcall_return(0); };
void XF_TermDataUpd(void *x)                          { os_appcall_return(TermDataUpd(x)); };
void XF_AcqDataUpd(DWORD x, struct ACQUIRER_TBL *y)    {os_appcall_return(UpdAcqTbl(x,y));}
void XF_EditIp(BYTE *x, DWORD y)                      {os_appcall_return(EditIp(x,y));}
void XF_EditPort(DWORD *x, DWORD y)                  {os_appcall_return(EditPort(x,y));}
void XF_TermIPFunc()                                  {TermIPFunc();os_appcall_return(0);}
void XF_SetGPRS()                                     {PPPTest();os_appcall_return(0);}
void XF_CONNECTPPP(BOOLEAN x)                         {os_appcall_return(ConnectPPP(x));}
// BatchSys Func
void XF_BatSysClear(int x)                            { BatSysClear(x); os_appcall_return(0);};
void XF_BatchFull(int x)                              { os_appcall_return(BatchFull(x));};
void XF_GetRecCount()                                 { os_appcall_return(GetRecCount());};
void XF_GetBatchRec(int x, void *y, int z)            { os_appcall_return(GetBatchRec(x, y, z));};
void XF_GetRevRec(int x, void *y, int z)              { os_appcall_return(GetRevRec(x, y, z));};
void XF_ClearRevRec(int x)                            { ClearRevRec(x); os_appcall_return(0);};
void XF_SaveBatRec(void *x, struct BATSYS_HDR *y)     { os_appcall_return(SaveBatRec(x, y));};
void XF_UpdateBatRec(int x, void *y, struct BATSYS_HDR *z) {os_appcall_return(UpdateBatRec(x, y, z));};
void XF_TraceInBatch(BYTE *x)                         { os_appcall_return(TraceInBatch(x)); };
void XF_TraceInReversal(BYTE *x)                      { os_appcall_return(TraceInReversal(x)); };

// Misc Func
void XF_GetAccessCode(void)                           { os_appcall_return(GetAccessCode()); };

void XF_ConnectAux(BYTE x, BYTE y)                    {os_appcall_return(ConnectAux(x, y));};
void XF_ResetAux(void)                                {os_appcall_return(ResetAux());};
void XF_my_SendAux(struct COMMBUF *x)                 {os_appcall_return(my_SendAux(x));};
void XF_my_RcvdAux(BYTE *x, WORD y)                   {os_appcall_return(my_RcvdAux(x, y));};

void XF_Send_Msg(struct COMMBUF *x)                   {os_appcall_return(Send_Msg(x));};
void XF_Receive_Msg(BYTE x, struct COMMBUF *y)        {os_appcall_return(Receive_Msg(x,y));};

//-----------------------------------------------------------------------------
//      Constant
//-----------------------------------------------------------------------------
const BYTE KSoftName[] = {"APM"};

const DWORD KExportFunc[] =    // Export Function Table
{
  (DWORD) APM_FUNC_COUNT,      // Importance!! Number of export functions!!!
  (DWORD) XF_GetHwHdl,
  (DWORD) XF_ClrKeyin,
  (DWORD) XF_GetKeyin,
  (DWORD) XF_WaitKey,
  (DWORD) XF_YesNo,
  (DWORD) XF_GetKbd,
  (DWORD) XF_SetKbdTO,
  (DWORD) XF_GetKbdTO,
  (DWORD) XF_PackComm,
  (DWORD) XF_PreConnect,
  (DWORD) XF_ConnectOK,
  (DWORD) XF_SendRcvd,
  (DWORD) XF_FlushComm,
  (DWORD) XF_ResetComm,
  (DWORD) XF_GetTermData          , // STIS Func
  (DWORD) XF_GetTermCfg           , 
  (DWORD) XF_GetCardCount         , 
  (DWORD) XF_GetCardTbl           , 
  (DWORD) XF_GetIssuerCount       , 
  (DWORD) XF_GetIssuerTbl         , 
  (DWORD) XF_GetAcqCount          , 
  (DWORD) XF_GetAcqTbl            , 
  (DWORD) XF_GetDescCount         , 
  (DWORD) XF_GetDescTbl           , 
  (DWORD) XF_GetLogoCount         , 
  (DWORD) XF_GetLogoTbl           , 
  (DWORD) XF_GetExParamCount      , 
  (DWORD) XF_GetExtraParam        , 
  (DWORD) XF_GetPending           , 
  (DWORD) XF_SetPending           , 
  (DWORD) XF_GetBatchNo           , 
  (DWORD) XF_SetBatchNo           , 
  (DWORD) XF_SelectAcquirer       , 
  (DWORD) XF_SetROC               , 
  (DWORD) XF_SetTrace             , 
  (DWORD) XF_StisClr              , 
  (DWORD) XF_StisAddTbl           , 
  (DWORD) XF_TermDataClr          , 
  (DWORD) XF_TermDataUpd          , 
  (DWORD) XF_AcqDataUpd           ,
  (DWORD) XF_EditIp               ,
  (DWORD) XF_EditPort             ,
  (DWORD) XF_TermIPFunc           ,
  (DWORD) XF_SetGPRS              ,
	(DWORD) XF_CONNECTPPP           ,
  (DWORD) XF_BatSysClear          , // BatchSys Func
  (DWORD) XF_BatchFull            , 
  (DWORD) XF_GetRecCount          , 
  (DWORD) XF_GetBatchRec          , 
  (DWORD) XF_GetRevRec            , 
  (DWORD) XF_ClearRevRec          , 
  (DWORD) XF_SaveBatRec           , 
  (DWORD) XF_UpdateBatRec         , 
  (DWORD) XF_TraceInBatch         , 
  (DWORD) XF_TraceInReversal      , 
  (DWORD) XF_GetAccessCode        , // Misc Func
  (DWORD) XF_ConnectAux           , //
  (DWORD) XF_ResetAux             , //
  (DWORD) XF_my_SendAux           , //
  (DWORD) XF_my_RcvdAux           , //
  (DWORD) XF_SendRcvd_my,
  (DWORD) XF_Receive_gprs,
  (DWORD) XF_Send_Msg             , //
  (DWORD) XF_Receive_Msg          , //
  (DWORD) NULL,
};


static const BYTE KEcrAppMap[ECR_MAXCMD_SUPPORT] = {
  0x00,    // ECR_PP300_CMD => No App / DLL only
  0x11,    // ECR_EDC_CMD => EDC
};

//*****************************************************************************
//  Function        : VirginInit
//  Description     : Perform virgin initialization.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
int VirginInit(void)
{
  struct MW_FILE_HDR file_hdr;
  int    found;

  Disp2x16Msg(KVirginInit, MW_LINE3, MW_CLRDISP|MW_BIGFONT);

  if (KDLL_CheckTMSFile())//tms+ zx 110315
    return 0;

  // Clear Up all old files
  found = fDSearchMW(TRUE, &file_hdr);
  while (found != -1) {
    fDeleteMW(file_hdr.sb_name);
    found = fDSearchMW(TRUE, &file_hdr);
  }
  fCommitAllMW();
  return 0;
}
//*****************************************************************************
//  Function        : GlobalsInit
//  Description     : Initialization global variables.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
void GlobalsInit(void)
{
  DWORD i, idx;
  struct MW_APPL_INFO app_info;
  char filename[32];
  struct TERM_DATA term_data;

  Disp2x16Msg(KSystemInit, MW_LINE3, MW_CLRDISP|MW_BIGFONT);
  EMVUtilStart();
  DispLineMW("Init Term Data", MW_MAX_LINE, MW_CLREOL|MW_SPFONT);
  TermDataInit();
  DispLineMW("Init STIS Data", MW_MAX_LINE, MW_CLREOL|MW_SPFONT);
  STISInit();
  ExParamInit();
  DispLineMW("Init Batch", MW_MAX_LINE, MW_CLREOL|MW_SPFONT);
  if (!BatSysInit(GetAcqCount())) {
    DispLineMW("Batch Init Fail!", MW_LINE1, MW_CLRDISP|MW_REVERSE|MW_BIGFONT);
    WaitKey(KBD_TIMEOUT);
    ResetMW();
  }

  // init table
  for (i = 0; i < sizeof(gApmMenu)/sizeof(struct RMENUDAT); i++) {
    gApmMenu[i].iID = -1;
  }

  idx = 0;
  // Add Application List
  for (i = 0; i < MAX_APP_LIST; i++) {
    gApmMenu[idx].iID = -1;
    if (AppInfoGetMW(i+K_UserID, &app_info)) {
      memset(gApmMenu[idx].sbName, 0, sizeof(gApmMenu[idx].sbName));
      memcpy(gApmMenu[idx].sbName, &app_info.sb_app_name[2], 10);
      gApmMenu[idx].sbName[strlen(gApmMenu[idx].sbName)] = ' ';
      gApmMenu[idx].iID = i+K_UserID;
      idx++;
    }
  }

  // Add APM function List, skip power option
  for (i=0; i < MAX_APM_FUNC-1; i++) {
    gApmMenu[idx].iID = i + APM_FUNC_START;
    memset(gApmMenu[idx].sbName, 0, sizeof(gApmMenu[idx].sbName));
    strcpy(gApmMenu[idx].sbName, KAPMFuncName[i]);
    idx++;
  }
  DispLineMW("Init Hardware", MW_MAX_LINE, MW_CLREOL|MW_SPFONT);
  InitAllHw();
  DispLineMW("Init Comm", MW_MAX_LINE, MW_CLREOL|MW_SPFONT);
  CommInit();

  // Init External Secure Channel
  // Aux Port connect to external pinpad (PP300)
  if (GetTermData(&term_data)) {
    if (term_data.b_ppad_port != 0) {
      switch (term_data.b_ppad_port)  {
         case 1:
           strcpy(filename, DEV_AUX0);
           break;
         case 2:
           strcpy(filename, DEV_AUX1);
           break;
         case 3:
           strcpy(filename, DEV_AUX2);
           break;
      }
      if (!SChnlSetupMW(filename, FALSE)) {   // Do not inject new key
        Disp2x16Msg("EPPAD Init Err! Please Check... ", MW_LINE3, MW_CLRDISP|MW_BIGFONT);
        WaitKey(KBD_TIMEOUT);
      }
    }
  }
}
//*****************************************************************************
//  Function        : GlobalsCleanUp
//  Description     : Clean Up all allocated globals.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
void GlobalsCleanUp(void)
{
  //CloseAllHw();
}
//*****************************************************************************
//  Function        : ECRRequest
//  Description     : Process ECR request if available.
//  Input           : aECRData;     // Buffer for ecrdata.
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
BOOLEAN ECRRequest(struct ECRDATA *aECRData)
{
  T_APP_INFO app_info;
  DWORD ecr_len;

  if (ECR_RxRdy()) {
    ecr_len = ECR_Rcvd(aECRData, sizeof(struct ECRDATA));
    if (ecr_len > 0) {
      switch (aECRData->b_cla) {
        case ECR_PP300_CMD:
          ECR_Clear();
          PP300Cmd(aECRData, ecr_len);
          break;
        case ECR_EDC_CMD:
          if (KEcrAppMap[ECR_EDC_CMD] != 0x00) {
            if (os_app_info(KEcrAppMap[ECR_EDC_CMD], &app_info)) {
              SwitchAppMW(KEcrAppMap[ECR_EDC_CMD], 0, 0, 0);
              ecr_len = ECR_Rcvd(aECRData, sizeof(struct ECRDATA));
            }
            if ((ecr_len > 0) && (aECRData->b_cla == ECR_EDC_CMD))
              ECR_Clear();
            break;
          }
          // Fall Thru;
        default:
          DispLineMW("APP Not Found!", MW_LINE3, MW_CLRDISP|MW_BIGFONT);
          LongBeep();
          ECR_Clear();
      }
      return TRUE;
    }
  }
  return FALSE;
}
//*****************************************************************************
//  Function        : Coremain
//  Description     : Your application code start here.
//  Input           : N/A
//  Return          : N/A
//  Note            : N/A
//  Globals Changed : N/A
//*****************************************************************************
int Coremain(DWORD aParam1, DWORD aParam2, DWORD aParam3)
{
  int     select;
  BOOLEAN disp_chg;
  DWORD   keyin=0;
  T_APP_INFO app_info;
  struct ECRDATA *pECRData = NULL;
  struct TERM_DATA term_data;
  struct  GLOC loc;

  if (os_app_info(ECRDLL_ID, &app_info)) {
    if (GetTermData(&term_data)) {
      if (term_data.b_ecr_port != 0) {
        switch (term_data.b_ecr_port)  {
           case 1:
             keyin = ECR_AUXD;
             break;
           case 2:
             keyin = ECR_AUX1;
             break;
           case 3:
             keyin = ECR_AUX2;
             break;
        }
        pECRData = (struct ECRDATA *)MallocMW(sizeof(struct ECRDATA));
        if (pECRData != NULL) {
           ECR_Start(keyin|ECR_USE_SEQ);
        }  
      }
    }
  }

#if (R700|TIRO|PR608)  
  ThreadCreateMW(ShowTxRxLed, 2);
#endif 

  if (GetSTISMode() == TRANS_MODE) {
    EMVInit();
  }


  select = -1;
  disp_chg = TRUE;
  while (1) {
     SleepMW();
     // Process ECR Req 
     if (pECRData != NULL) {
       if (ECRRequest(pECRData)) {
         disp_chg = TRUE;
       }
     }
//goto entry;
     if (disp_chg) {
       // Idle Display
       DispLineMW("Appl.", MW_LINE4+13, MW_CLRDISP|MW_SPFONT);
       DispLineMW("Manager", MW_LINE5+13, MW_SPFONT);
       #if (R700|TIRO|PR608)  
       ShowBWLogo(KBWSpectraLogo, sizeof(KBWSpectraLogo));
       #else
       loc.wPosX = 18;
       loc.wPosY = 10;
       loc.wWidth = KSpectraSym[5]*256+KSpectraSym[4];
       loc.wHeight= KSpectraSym[7]*256+KSpectraSym[6];
       //ShowGraphic(&loc, &KSpectraSym[8]);
       #endif       
       disp_chg = FALSE;
     }
     //keyin = GetCharMW();
     //if (keyin == 0) continue;


//entry:
#if (T800)
    select = RMenuSel(gApmMenu, KSpectraSym, "\x0E\x10\x1B\x06\x02SPECTRA\x12\x1B\x07\x03""Appl.\x1B\x08\x03Manager\x0F");
#else
    select = RMenuSel(gApmMenu, NULL, NULL);
#endif
    if (select >= APM_FUNC_START) {
      if (select == RMNU_POWEROFF)
        select = APM_PWR|APM_FUNC_START;
      APMFunc(select);
      continue;
    }
    if (select > 0) {
      SwitchAppMW(select, 0, 0, 0);
      disp_chg = TRUE;
    }
    disp_chg = TRUE;
    SleepMW();
  }
  if (pECRData != NULL) {
    ECR_Stop();
    FreeMW(pECRData);
  }
#if (R700|TIRO|PR608)  
  ThreadDeleteMW(ShowTxRxLed);
#endif  
  ResetMW();
  return 0;
}
